﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MoneyWentWhere.DataModel;
using MoneyWentWhere.DataModel.Binding;
using System.Diagnostics;
using MoneyWentWhere.WinFormsUI.Properties;
using System.Drawing.Drawing2D;
using MoneyWentWhere.WinFormsUI.UI.DataGrid;

namespace MoneyWentWhere.WinFormsUI.UI
{
    public partial class AccountPage : UserControl
    {
        Account _account;
        TxDataGridPainter _gridPainter;


        public AccountPage()
        {
            InitializeComponent();

            this.Visible = false;
            this.Enabled = false;

            _gridPainter = new TxDataGridPainter(this.dgTransactions);
        }

        public Account Account
        {
            get { return _account; }
            set
            {
                if (value == _account) { return; }

                SetAccount(value, -1, true);
            }
        }

        public void SetAccount(Account value, int selectedRowIndex, bool focus)
        {
            // Switch account
            if (value != _account)
            {
                _account = value;

                if (_account == null)
                {
                    this.Visible = false;
                    this.Enabled = false;
                }
                else
                {
                    this.Visible = true;
                    this.Enabled = true;

                    // Set account info
                    accountBS.DataSource = _account;

                    // Set currency
                    currencyListBS.DataSource = _account.DataSet.Currencies;
                    cbAcctCurrency.SelectedItem = _account.Currency;
                    cbAcctCurrency.Text = _account.Currency.ToString();

                    // Set transaction table
                    // BUGFIX: if we don't stop the edit, an IndexOutOfBounds ex is thrown
                    transactionListBS.CancelEdit();
                    transactionListBS.DataSource = _account.Transactions;
                }
            }

            // Select
            if (_account != null)
            {
                if (focus)
                {
                    this.Select();
                    dgTransactions.Select();
                }

                if (selectedRowIndex < 0)
                {
                    selectedRowIndex = dgTransactions.Rows.Count - 1;
                }

                // Clear old selection
                foreach (DataGridViewCell cell in dgTransactions.SelectedCells)
                {
                    cell.Selected = false;
                }

                // Set new selection
                if (selectedRowIndex <= dgTransactions.Rows.Count)
                {
                    //dgTransactions.Rows[selectedRowIndex].Selected = true;
                    dgTransactions.FirstDisplayedScrollingRowIndex = selectedRowIndex;

                    // Editing the withdrawal amount
                    DataGridViewCell curCell = dgTransactions[ctWithdrawal.Index, selectedRowIndex];
                    curCell.Selected = true;
                    dgTransactions.CurrentCell = curCell;
                    if (focus)
                    {
                        dgTransactions.BeginEdit(false);
                    }
                }
            }

        }

        private void cbAcctCurrency_Validating(object sender, CancelEventArgs e)
        {
            String curId = cbAcctCurrency.Text.Trim();
            if (String.IsNullOrEmpty(curId))
            {
                e.Cancel = true;
                return;
            }

            curId = curId.ToUpperInvariant();
            if (Account.DataSet.Currencies[curId] == null)
            {
                Currency curr = new Currency(curId);
                Account.DataSet.Currencies.Add(curr);
                Account.Currency = curr;
                cbAcctCurrency.Text = curr.ToString();
            }
        }

        private void cbAcctCurrency_SelectedIndexChanged(object sender, EventArgs e)
        {
            Currency curr = cbAcctCurrency.SelectedItem as Currency;
            if (Account != null && curr != null)
            {
                Account.Currency = curr;
            }

        }

        private void dgTransactions_SelectionChanged(object sender, EventArgs e)
        {
            Trace.WriteLine("SelectionChanged: " + dgTransactions.SelectedCells);
            // Transaction t = SelectedTransaction;
        }

        private void tbInsert_Click(object sender, EventArgs e)
        {
            int index = transactionListBS.CurrencyManager.Position;
            Account.CreateTransaction(0, suggestedIndex: index + 1);
        }

        private void tbDelete_Click(object sender, EventArgs e)
        {
            transactionListBS.RemoveCurrent();
        }

        private void transactionListBS_ListChanged(object sender, ListChangedEventArgs e)
        {
            if (e.ListChangedType == ListChangedType.ItemAdded)
            {
                transactionListBS.Position = e.NewIndex;
            }

        }

        private void dgTransactions_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {   
            MessageBox.Show(this, "Date entry error.\r\n" + e.Exception.Message,
                "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 
        }

        private void OnKeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                CommitBindingValue(sender as Control);
            }
        }
        void CommitBindingValue(Control c)
        {
            if (c != null && c.DataBindings != null)
            {
                foreach (Binding b in c.DataBindings)
                {
                    b.WriteValue();
                }
            }
        }

        private void tbUp_Click(object sender, EventArgs e)
        {
            Transaction tx = SelectedTransaction;
            if (tx == null) { return; }

            int index = Account.Transactions.IndexOf(tx);
            if (index == 0) { return; }

            // Adjust date if needed
            Transaction prev = Account.Transactions[index - 1];
            if (tx.Date > prev.Date)
            {
                tx.Date = prev.Date;
            }

            // Move
            Account.Transactions.RemoveItem(index, false);
            Account.Transactions.Insert(index - 1, tx);
        }

        private void tbDown_Click(object sender, EventArgs e)
        {
            Transaction tx = SelectedTransaction;
            if (tx == null) { return; }

            int index = Account.Transactions.IndexOf(tx);
            if (index >= Account.Transactions.Count - 1) { return; }

            // Adjust date if needed
            Transaction next = Account.Transactions[index + 1];
            if (tx.Date < next.Date)
            {
                tx.Date = next.Date;
            }

            // Move
            Account.Transactions.RemoveItem(index, false);
            Account.Transactions.Insert(index + 1, tx);
        }

        Transaction SelectedTransaction
        {
            get 
            {
                if (dgTransactions.SelectedRows.Count == 1)
                {
                    return dgTransactions.SelectedRows[0].DataBoundItem as Transaction;
                }
                return null;
            }
        }

        private void dgTransactions_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
        {
            /*
            if (dgTransactions.Columns[e.ColumnIndex] == ctAccountBalance)
            {
                // Prompt to proceed or not if we're about to convert *transfer*
                // to *reconcile*. This involves some data loss, so good to ask.
                Transaction tx = dgTransactions.Rows[e.RowIndex].DataBoundItem as Transaction;
                if (tx != null && 
                    tx.Kind == TransactionKind.Transfer)
                {
                    decimal val;
                    if (decimal.TryParse((String)e.FormattedValue, out val) &&
                        tx.RecoBalance != val)
                    {
                        DialogResult res = MessageBox.Show("Remove *transfer* and change transaction to *reconcile*?",
                            "Warning", MessageBoxButtons.YesNo);

                        if (res == DialogResult.No)
                        {
                            e.Cancel = true;
                            dgTransactions.CancelEdit();
                        }
                    }
                }
            }
            */
        }

        private void dgTransactions_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
        {
            _gridPainter.MouseOverRow = e.RowIndex;
        }

        private void dgTransactions_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if (dgTransactions.Columns[e.ColumnIndex] == ctTags 
                && e.Value != null)
            {
                TagSet tags = (TagSet)e.Value;
                e.Value = String.Join(" ", tags);
                e.FormattingApplied = true;
            }
        }

        private void dgTransactions_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
        {
            if (dgTransactions.Columns[e.ColumnIndex] == ctTags
                && e.Value != null)
            {
                String val = (String)e.Value;
                var tags = val.Split(' ').Select(x => x.Trim().ToLower());
                e.Value = new TagSet(tags);
                e.ParsingApplied = true;
            }
        }

    }

}
